using UnityEngine;
using System.Collections;


public	enum eSidescrollLimitMode
{
	Unlimited	= 0,
	HardLimited	= 1,
	SoftLimited	= 2,
	SoftHelped	= 3
}


[System.Serializable]
public class Mover2D
{
	#region Variables
		#region movement vars
	    	private	SidescrollMovementData 	m_sCurVars;
	    	private	SidescrollMovementData 	m_sFutureVars;
		
	    	private	SideScrollExternData 	m_sExternCurVars;
	    	private	SideScrollExternData 	m_sExternFutureVars;
			
			private	bool					m_bExternalAcceleration		=	false;		
			private	bool					m_bExternalFriction			=	false;		
			private	bool					m_bExternalResistance		=	false;		
			private	bool					m_bExternalConstSpeed		=	false;		
			//private	bool				m_bExternalHitForce			=	false;		
			private	bool					m_bExternalParametarsActive	=	false;		
	
			private float					m_fInputSqrMagnitudeToFast;	// The square magnitude that the inpud needs to be considered fast
			public	bool					m_bIsInputFast;				// Shows if the input received is fast or slow
			public	bool					m_bFastSpeedLocked;			// lock input to set it as slow
		#endregion
	
		#region Transition vars
			private	float					m_fTimeToFutureValsTotal; 
			private	float					m_fTimeToFutureValsCur;
	
			private	float					m_fTimeToExtFutureValsTotal; 
			private	float					m_fTimeToExtFutureValsCur; 
		#endregion
	
		#region Current speed
	        private	Vector2        			m_vSpeedCurrent;            // The current speed
	        private	float           		m_fSpeedSoftMax;      		// The current max speed related to the input
			private	float					m_fSpeedMagnitude;  
		#endregion
	
		#region Time
			private float					m_fDeltaTime;				// It will be shared between methods
		#endregion
		
		#region Hit vars
			public	float					m_fHitTimeCoef		= 1.0f;	// If 0, no stun time if 1, normal time
			public	float					m_fHitTBounceCoef	= 0.1f;	// If 0, no extra bounce. Speed added depending on how oposite directiosn are
			private float					m_fHitApplyTimeTotal;
			private float					m_fHitApplyTimeCur;
			//private Vector2				m_v2HitForce;
			//public	float				m_fHitMovementCoef	= 1.0f;	// If 0, no movement during hit time if 1, normal movement
			//private AnimationCurve		m_acHitSpeedCurve;
		#endregion
	
		#region Auxiliar variables (stored here not to create them every frame)
			private Vector2					m_vAcceleration;
			private Vector2					m_v2DeltaDisplacement;
			private Vector2					m_v2Zero	= Vector2.zero;
			private float					m_fAux;	
		#endregion
	
		#region Gameplay Area
			public	SidescrollGameplayArea	m_sgaGameplayArea;
			public	eSidescrollLimitMode	m_eLimitaitonMode;
		#endregion
	#endregion
	
	#region Propertys
		public float DeltaTime
		{
			get{
				return m_fDeltaTime;
			}
			set{
				m_fDeltaTime = value;
			}
		}
		
		public bool SlowLock
		{
			get{
				return m_bFastSpeedLocked;
			}
			set{
				m_bFastSpeedLocked = value;
			}
		}
	#endregion
	
	#region Interaction Methods
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public void	InitData(float _fSqrInputFast, ref SidescrollMovementData _stMovement, ref SideScrollExternData _stExtern)
	{
		m_fInputSqrMagnitudeToFast 	= _fSqrInputFast;
		m_sCurVars					= new SidescrollMovementData();
		m_sFutureVars				= new SidescrollMovementData();
		
		m_sExternCurVars			= new SideScrollExternData();
		m_sExternFutureVars			= new SideScrollExternData();
		
		SetNewVariablesNow			( ref _stMovement);
		SetNewExternVariablesNow	( ref _stExtern);
		
		m_vSpeedCurrent 			= m_v2Zero; 
		m_fSpeedSoftMax				= 0.0f;
		m_fSpeedMagnitude			= 0.0f;
		
		CheckExternalActiveValues();
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public Vector2 GetNewDisplacement(ref Vector2 _vInput, float _fDeltaTime)
	{
		// Init data
        //---------------------------------------------------------------------------------------------------------
		m_fDeltaTime 			=	_fDeltaTime;
		m_v2DeltaDisplacement	=	m_v2Zero;
		
		
		// Apply the hit movement reduction
        //---------------------------------------------------------------------------------------------------------
		if(m_fHitApplyTimeCur < m_fHitApplyTimeTotal)
			ApplyAndUpdateHitMovementReduction(ref _vInput);
		
		// Blend the values
        //---------------------------------------------------------------------------------------------------------
		UpdateMovementAndExternalValues();
		
		
		// Update the soft max speed (ED)
        //---------------------------------------------------------------------------------------------------------
        ComputeSoftMaxSpeed(ref _vInput);
		
		
		// Update the speed through acceleration (ED)
        //---------------------------------------------------------------------------------------------------------
		ApplyAcceleration(ref _vInput);       
        		
		
		// Apply realistic friction to exceeding speeds
        //---------------------------------------------------------------------------------------------------------
		ApplyExceedingSpeedFriction();
		
		
        // Apply Stabilizers (ED)
        //---------------------------------------------------------------------------------------------------------
		ApplyStabilizers(ref _vInput);
		

        // Limit the speed by the current max value(ED)
        //---------------------------------------------------------------------------------------------------------
       	//ApplySpeedLimitMax(ref _vInput);
		
		
		// If there are no external forces that's it
        //---------------------------------------------------------------------------------------------------------
		if(!m_bExternalParametarsActive)
		{
			// Prepare the displacement forces
			m_v2DeltaDisplacement	= m_vSpeedCurrent * m_fDeltaTime; 
		}
		
		// If there are external update the total speed and total dispolacement
        //---------------------------------------------------------------------------------------------------------
		else
		{
	        // Apply the external acceleration (ED)
	        //---------------------------------------------------------------------------------------------------------
			if(m_bExternalAcceleration)
	       		ApplyExternalAcceleration();
			
			
			// Apply the external friction
	        //---------------------------------------------------------------------------------------------------------
			if(m_bExternalFriction)
				ApplyExternalFriction();
			
	
	        // Apply the resistance only if going against it (ED)
	        //---------------------------------------------------------------------------------------------------------
			if(m_bExternalResistance)
				ApplyForceResistance();
			
			
			// Update the basic displacement
	        //---------------------------------------------------------------------------------------------------------
			m_v2DeltaDisplacement = m_vSpeedCurrent * m_fDeltaTime;
			
			
			// Apply the constant velocity
	        //---------------------------------------------------------------------------------------------------------
			if(m_bExternalConstSpeed)
				m_v2DeltaDisplacement +=  m_sExternCurVars.m_vExternalConstVelocity * m_fDeltaTime;
		}
		
		
		// Return the resulting Displacement
        //---------------------------------------------------------------------------------------------------------
		return m_v2DeltaDisplacement;
	}
    
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public void PlaceMeWorld(ref Vector2 _vInput, float _fDeltaTime, Transform _tMe)
	{
		GetNewDisplacement(ref _vInput, _fDeltaTime);
		Vector2 v2Position = _tMe.position;
		v2Position.x += m_v2DeltaDisplacement.x;
		v2Position.y += m_v2DeltaDisplacement.y;
		
		ApplyLimitationWorld(ref v2Position);
		
		// set the new position
		_tMe.position = v2Position;
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public void PlaceMeRelative(ref Vector2 _vInput, float _fDeltaTime, Transform _tMe)
	{
		GetNewDisplacement(ref _vInput, _fDeltaTime);
		Vector3 v3Position	=	_tMe.position;
		v3Position			=	m_sgaGameplayArea.GetRelativePositionFromWorld(ref v3Position);
		v3Position			+=	(m_v2DeltaDisplacement.x * m_sgaGameplayArea.transform.right) 
							+	(m_v2DeltaDisplacement.y * m_sgaGameplayArea.transform.up);
		
		ApplyLimitationRelative(ref v3Position);
		
		// set the new position
		_tMe.position = v3Position;
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	private void ApplyLimitationWorld(ref Vector2 _v2Position)
	{
		switch(m_eLimitaitonMode)
		{
			case eSidescrollLimitMode.HardLimited:
				if(_v2Position.x 	>	m_sgaGameplayArea.transform.position.x + m_sgaGameplayArea.m_v3Size.x)
				{
					_v2Position.x 	= 	m_sgaGameplayArea.transform.position.x + m_sgaGameplayArea.m_v3Size.x;
					StopSpeedInRelativeDirection(true, false);
				}
				else if(_v2Position.x < 	m_sgaGameplayArea.transform.position.x - m_sgaGameplayArea.m_v3Size.x)
				{
					_v2Position.x 	= 	m_sgaGameplayArea.transform.position.x - m_sgaGameplayArea.m_v3Size.x;
					StopSpeedInRelativeDirection(true, false);
				}
				if(_v2Position.y 	> 	m_sgaGameplayArea.transform.position.y + m_sgaGameplayArea.m_v3Size.y)
				{
					_v2Position.y 	= 	m_sgaGameplayArea.transform.position.y + m_sgaGameplayArea.m_v3Size.y;
					StopSpeedInRelativeDirection(false, true);
				}
				else if(_v2Position.y < 	m_sgaGameplayArea.transform.position.y - m_sgaGameplayArea.m_v3Size.y)
				{
					_v2Position.y 	= 	m_sgaGameplayArea.transform.position.y - m_sgaGameplayArea.m_v3Size.y;
					StopSpeedInRelativeDirection(false, true);
				}
			break;
		
		}
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	private void ApplyLimitationRelative(ref Vector3 _v2Position)
	{
		switch(m_eLimitaitonMode)
		{
			case eSidescrollLimitMode.HardLimited:
				if(_v2Position.x 	>	m_sgaGameplayArea.m_v3Size.x)
				{
					_v2Position.x 	= 	m_sgaGameplayArea.m_v3Size.x;
					StopSpeedInRelativeDirection(true, false);
				}
				else if(_v2Position.x < -m_sgaGameplayArea.m_v3Size.x)
				{
					_v2Position.x 	= 	-m_sgaGameplayArea.m_v3Size.x;
					StopSpeedInRelativeDirection(true, false);
				}
				if(_v2Position.y 	> 	m_sgaGameplayArea.m_v3Size.y)
				{
					_v2Position.y 	= 	m_sgaGameplayArea.m_v3Size.y;
					StopSpeedInRelativeDirection(false, true);
				}
				else if(_v2Position.y < -m_sgaGameplayArea.m_v3Size.y)
				{
					_v2Position.y 	= 	-m_sgaGameplayArea.m_v3Size.y;
					StopSpeedInRelativeDirection(false, true);
				}
			break;	
		}
	}
	
	//---------------------------------------------------------------------------------------------------------
	// Give _v2Direction normalized
    //---------------------------------------------------------------------------------------------------------
	public void Hit(ref Vector2 _v2Force, float _fTime, bool _bIgnoreResistance, bool _bIgnoreBounce)
	{
		m_fAux						=	Mathf.Max(0.0f, Vector2.Dot(m_vSpeedCurrent, -_v2Force) * m_fHitTBounceCoef);
		m_vSpeedCurrent				+=	_v2Force	* (_bIgnoreResistance	? 1.0f : m_sCurVars.m_fHitReductionCoef)
													* (_bIgnoreBounce		? 1.0f : (1.0f + m_fAux ));
		
		m_fHitApplyTimeCur			=	0.0f;
		m_fHitApplyTimeTotal		=	_fTime * m_fHitTimeCoef;
		
		/*
		m_v2HitForce				=	_v2Force;
		m_acHitSpeedCurve			=	_acHitSpeedCurve;
		
		// Activate the forces
		m_bExternalHitForce			=	true;
		m_bExternalParametarsActive	=	true;
		*/
	}
	
	#endregion
	
	#region collision effects
    
	//---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	public void ResetSpeeds()
	{
		m_vSpeedCurrent			= m_v2Zero;
	}

    //---------------------------------------------------------------------------------------------------------
	// give _v3Dir normalized 
    //---------------------------------------------------------------------------------------------------------
	public void StopSpeedInDirection(ref Vector2 _v2Dir)
	{
		m_vSpeedCurrent 		-= _v2Dir * Vector2.Dot(m_vSpeedCurrent			, _v2Dir);
	}

	//---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	public void StopSpeedInRelativeDirection(bool _bXCoord, bool _bYCoord)
	{
		if(_bXCoord)
		{
			m_vSpeedCurrent.x 		= 0.0f;
		}
		if(_bYCoord)
		{
			m_vSpeedCurrent.y 		= 0.0f;
		}
	}

	#endregion
		
	#region SpeedCalculations
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplyAcceleration(ref Vector2 _vInput)
	{
		if(_vInput == m_v2Zero)
		{
			return;
		}
		
		// Study the oposition of movement
        //---------------------------------------------------------------------------------------------------------
		m_fAux			= Vector2.Angle(_vInput, m_vSpeedCurrent);
		m_fAux			= (Mathf.Cos(m_fAux * Mathf.Deg2Rad) + 1) * 0.5f;
		
		
		// Get the acceleration (ED)
        //---------------------------------------------------------------------------------------------------------
		m_vAcceleration		= _vInput / _vInput.magnitude * Mathf.Abs( m_sCurVars.m_fAcceleration	* m_fAux 
		                                 + m_sCurVars.m_fBrake			* (1 - m_fAux));
		
		// Limit the acceleration if the speed max is reached (ED)
        //---------------------------------------------------------------------------------------------------------
		// store the current speed module
		m_fSpeedMagnitude	=	m_vSpeedCurrent.magnitude;
		
		// update the speed normally
		m_vSpeedCurrent 	+=	m_vAcceleration * m_fDeltaTime;
		
		// check if we are going in the same direction, otherwise we wont modify the speed
		if(m_fAux > 0.5f) // it is 0.5 because we have the coef = (cos + 1) + 0.5 so the cos is 0 when the coef is 0.5
		{
			// If the speed was allready surpassing the limit, we wil leave the speed module intact but we will turn the vector
			if(m_fSpeedMagnitude	>	m_fSpeedSoftMax)
			{
				m_vSpeedCurrent		*=	m_fSpeedMagnitude / m_vSpeedCurrent.magnitude;
				m_fSpeedMagnitude	=	m_fSpeedSoftMax;
			}
			// If the speed is surpassing the limit this frame, we wll increase the speed but limit the module by the max
			else 
			{
				m_fSpeedMagnitude	=	m_vSpeedCurrent.magnitude;
				if(m_fSpeedMagnitude>	m_fSpeedSoftMax)
				{
					m_vSpeedCurrent	*=	m_fSpeedSoftMax / m_fSpeedMagnitude;
				}
			}
		}
	}
	
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplyStabilizers(ref Vector2 _vInput)
	{
		// If the speed is zero, nothing to stabilize
    	//---------------------------------------------------------------------------------------------------------
		if(m_vSpeedCurrent == m_v2Zero)
		{
			return;
		}
		
		//if the speed is exceeding the soft max speed, apply full stabilizers
    	//---------------------------------------------------------------------------------------------------------
		/*if(m_fSpeedMagnitude	>	m_fSpeedSoftMax) // m_fSpeedMagnitude is calculated at the end of the acceleration step
		{
			m_vSpeedCurrent = Maths.Vec2LinearReduction(ref m_vSpeedCurrent , m_sCurVars.m_fStabilizersMax * m_fDeltaTime);
			return;
		}*/
		
		m_fAux			= Vector2.Angle(_vInput, m_vSpeedCurrent);
		m_fAux			= Mathf.Cos(m_fAux * Mathf.Deg2Rad);
		
		// if going to the same direciton, do not apply stabilizers
    	//---------------------------------------------------------------------------------------------------------
		if(m_fAux > 0.5f)
		{
			return;
		}
		
		// Apply more or less speed depending on the input direciton and the speed
    	//---------------------------------------------------------------------------------------------------------
		m_fAux			= Mathf.Max(m_fAux, 0.0f) * m_fSpeedMagnitude / m_sCurVars.m_fSpeedHardMaxFast;
		if(m_fAux >= 0.0f)
		{
			m_fAux		= Maths.FloatMap( 0.0f, 0.5f, m_sCurVars.m_fStabilizersMin, m_sCurVars.m_fStabilizersMax
			                         		, 0.5f - m_fAux);
		}
        else
		{
			m_fAux		= m_sCurVars.m_fStabilizersMax;
		}
		m_vSpeedCurrent = Maths.Vec2LinearReduction(ref m_vSpeedCurrent , m_fAux * m_fDeltaTime);
	}	
	
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplyExceedingSpeedFriction()
	{
		if(m_fSpeedMagnitude > m_sCurVars.m_fSpeedHardMaxFast)
		{
			m_vSpeedCurrent = Maths.Vec2LinearReduction(ref m_vSpeedCurrent , m_sCurVars.m_fFrictionExtra 
			                                            * m_fSpeedMagnitude * m_fSpeedMagnitude * m_fDeltaTime);
		}
	}
	
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ComputeSoftMaxSpeed(ref Vector2 _vInput)
	{
		// The theoretical max speed depends on the input strength	(ED)
		if(!m_bFastSpeedLocked && _vInput.sqrMagnitude > m_fInputSqrMagnitudeToFast)
		{
			m_fAux	= m_sCurVars.m_fSpeedHardMaxFast;
		}
		else
		{
			m_fAux 	= m_sCurVars.m_fSpeedHardMaxSlow;
		}
		
		// The soft max speed increases instantly and decreases slowly	(ED)
        if(m_fAux 	< m_fSpeedSoftMax)
        {
            m_fSpeedSoftMax = Maths.FloatLinearBlend( m_fSpeedSoftMax, m_fAux
                                                     , m_sCurVars.m_fSpeedMaxSofteningSpeed * m_fDeltaTime);
        }
        else
        {
            m_fSpeedSoftMax = m_fAux; 
        }
	}	
	
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplySpeedLimitMax(ref Vector2 _vInput)
	{			
		if(m_vSpeedCurrent == m_v2Zero)
		{
			return;
		}
		
		// Limit the speed (ED)
        //---------------------------------------------------------------------------------------------------------
		m_fSpeedMagnitude		=	m_vSpeedCurrent.magnitude;
		if(m_fSpeedMagnitude 	>	m_fSpeedSoftMax)
		{
			m_vSpeedCurrent		*=	m_fSpeedSoftMax / m_fSpeedMagnitude;
			m_fSpeedMagnitude	=	m_fSpeedSoftMax;
		}
	}
	
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplyExternalAcceleration()
	{
        m_vSpeedCurrent += m_sExternCurVars.m_vExternalAcceleration * m_fDeltaTime;
	}	
	
 	//---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplyExternalFriction()
	{
		if(m_vSpeedCurrent != m_v2Zero)
		{
			m_fSpeedMagnitude	= m_vSpeedCurrent.magnitude;
			m_vSpeedCurrent		= Maths.Vec2LinearReduction(ref m_vSpeedCurrent
			                                             , m_sExternCurVars.m_fExternalConstFriction
			                                             * m_fSpeedMagnitude * m_fSpeedMagnitude * m_fDeltaTime);
		}
	}

    //---------------------------------------------------------------------------------------------------------
	// The resistance is related to directions 	(ED)
    //---------------------------------------------------------------------------------------------------------
	private void ApplyForceResistance()
	{
		m_fAux				=	Vector2.Dot(m_sExternCurVars.m_vResistance, m_vSpeedCurrent);
		if(m_fAux > 0.0f)
		{
        	m_vSpeedCurrent	-=	m_sExternCurVars.m_vResistance * m_fAux * m_fDeltaTime;
		}
	}
	
    //---------------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------------
	private void ApplyAndUpdateHitMovementReduction(ref Vector2 _vInput)
	{
		m_fHitApplyTimeCur	+=	m_fDeltaTime;
		_vInput				=	m_v2Zero;
		
		/*
		m_vAux					=	(m_fHitApplyTimeTotal - m_fHitApplyTimeCur) / m_fHitApplyTimeTotal;
		m_vAux					=	m_acHitSpeedCurve.Evaluate(m_vAux);
		m_vSpeedCurrent			+=	Maths.Vec2Blend	( ref m_v2HitForce, ref m_v2Zero, m_vAux) * m_fDeltaTime;
		m_fHitApplyTimeCur 		+=	m_fDeltaTime;
		if(m_fHitApplyTimeCur	>=	m_fHitApplyTimeTotal)
		{
			m_bExternalHitForce	= false;
			CheckExternalActiveValues();
		}
		*/
	}
	#endregion     
	
	#region Data setting and treatment
		//---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		public void SetNewVariables(ref SidescrollMovementData _sNewValues, float _fTimeToComplete) 
		{
			m_sFutureVars.Set(ref _sNewValues);
			
			m_fTimeToFutureValsTotal	=	_fTimeToComplete;
			
			// force re-blend (ED)
			m_fTimeToFutureValsCur		=	0.0f;
		}
		
	    //---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		public void SetNewVariablesNow(ref SidescrollMovementData _sNewValues) 
		{
			m_sFutureVars.Set	(ref _sNewValues);
			m_sCurVars.Set		(ref _sNewValues);
			
			
			// Forbid re blend   (ED)               
			m_fTimeToFutureValsCur		=	m_fTimeToFutureValsTotal;
		}
		
		//---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		public void SetNewExternVariables(ref SideScrollExternData _sNewValues, float _fTimeToComplete) 
		{
			m_sExternFutureVars.Set(ref	_sNewValues);
			
			m_fTimeToExtFutureValsTotal	=	_fTimeToComplete;
			
			// force re-blend (ED)
			m_fTimeToExtFutureValsCur	=	0.0f;
		}
		
	    //---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		public void SetNewExternVariablesNow(ref SideScrollExternData _sNewValues) 
		{
			m_sExternFutureVars.Set	(ref _sNewValues);
			m_sExternCurVars.Set	(ref _sNewValues);
			
			// Forbid re blend (ED)
			m_fTimeToExtFutureValsCur	=	m_fTimeToExtFutureValsTotal;
			
			CheckExternalActiveValues();
		}
		
	    //---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		private void UpdateMovementAndExternalValues()
		{
			// Update only when needed (ED)
			if(m_fTimeToFutureValsCur < m_fTimeToFutureValsTotal)
			{
				UpdateValuesBlend();
			}
			if(m_fTimeToExtFutureValsCur < m_fTimeToExtFutureValsTotal)
			{
				UpdateExternValuesBlend();
			}
		}
		
		//---------------------------------------------------------------------------------------------------------
		//---------------------------------------------------------------------------------------------------------
		private void CheckExternalActiveValues()
		{
			m_bExternalResistance 		=	m_sExternCurVars.m_vResistance 				!= m_v2Zero;
			m_bExternalAcceleration		=	m_sExternCurVars.m_vExternalAcceleration	!= m_v2Zero;
			m_bExternalFriction			=	m_sExternCurVars.m_fExternalConstFriction	!= 0.0f;
			m_bExternalConstSpeed		=	m_sExternCurVars.m_vExternalConstVelocity	!= m_v2Zero;
			//m_bExternalHitForce			=	m_fHitApplyTimeCur >= m_fHitApplyTimeTotal; // not necessary
		
			m_bExternalParametarsActive =	m_bExternalResistance	||	m_bExternalAcceleration 
										||	m_bExternalFriction		||	m_bExternalConstSpeed ;
										//||	m_bExternalHitForce;				  
		}
		
		//---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		private void UpdateValuesBlend()
		{
			// Update the timer (ED)
			m_fTimeToFutureValsCur += m_fDeltaTime;
			
			// Check completion (ED)
			if(m_fTimeToFutureValsCur > m_fTimeToFutureValsTotal)
			{
				m_fTimeToFutureValsCur = m_fTimeToFutureValsTotal;
			}
			
			// Get the blend coef (ED)
			m_fAux	= m_fTimeToFutureValsCur / m_fTimeToFutureValsTotal;
			
			// Blend all values (ED)
			m_sCurVars.Blend(ref m_sFutureVars, m_fAux);
		}
		
		//---------------------------------------------------------------------------------------------------------
	    //---------------------------------------------------------------------------------------------------------
		private void UpdateExternValuesBlend()
		{
			// Update the timer  (ED)
			m_fTimeToExtFutureValsCur += m_fDeltaTime;
			
			// Check completion (ED)
			if(m_fTimeToExtFutureValsCur > m_fTimeToExtFutureValsTotal)
			{
				m_fTimeToExtFutureValsCur = m_fTimeToExtFutureValsTotal;
				CheckExternalActiveValues();
			}
			
			// Get the blend coef (ED)
			m_fAux	= m_fTimeToExtFutureValsCur / m_fTimeToExtFutureValsTotal;
			
			// Blend all values (ED)
			m_sExternCurVars.Blend(ref m_sExternFutureVars, m_fAux);              
		}
	#endregion
}

